package turtle.system.doug;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import turtle.system.doug.turtleaction.TurtleActEvaluator;
import turtle.system.doug.turtleaction.TurtleActReverseEvaluator;
import turtle.system.doug.turtleaction.TurtleAction;
import turtle.system.doug.turtleaction.TurtleAddAction;
import turtle.system.pt.Bar;
import turtle.system.pt.BarSet;
import turtle.system.pt.DailyStopProfitExec;
import turtle.system.pt.MDD;
import turtle.system.pt.PriceData;
import turtle.system.pt.StatCalc;

/**
 * 2.0版,有當沖訊號
 * 
 * @author doug
 * 
 */
public class PriceDataRefineSellSystem {
	/* 當沖訊號以及已決定出場天的盤中停損價 */
	public static final boolean IS_NEED_EVALUATOR = false;
	public static final int HALF_FORCE_STOP_LOSS = 200;
    public static final int SKIP_NEXT_TRADE_PROFIT = 1100;
	
	public static boolean useReverse = false; 
	public static final int OUT_TRADE_AT_START = 0;
	public static final int OUT_TRADE_AT_END = 1;
	public static final int OUT_TRADE_AT_UNKNOWN = 2;
	/* 多單停損,空單停損,多單停利,空單停利,多單趨勢反轉,空單趨勢反轉 */
	public static final int[] DEFAULT_START_OR_NOT = new int[] {
			OUT_TRADE_AT_END, OUT_TRADE_AT_END, OUT_TRADE_AT_START,
			OUT_TRADE_AT_START, OUT_TRADE_AT_START, OUT_TRADE_AT_START };

	public static final int ADD_ACTION_OUT_STOPPROFIT_SHORT = 0;
	public static final int ADD_ACTION_OUT_STOPPROFIT_LONG = 1;
	public static final int ADD_ACTION_OUT_STOPLOSS_SHORT = 2;
	public static final int ADD_ACTION_OUT_STOPLOSS_LONG = 3;
	public static final int ADD_ACTION_OUT_TRENDREVERSE_SHORT = 4;
	public static final int ADD_ACTION_OUT_TRENDREVERSE_LONG = 5;
	public static final int ADD_ACTION_IN_SHORT = 6;
	public static final int ADD_ACTION_IN_LONG = 7;
	
	public static final int STOP_LOSS_LONG = 1;
	public static final int STOP_LOSS_SHORT = 2;
	public static final int STOP_PROFIT_LONG = 3;
	public static final int STOP_PROFIT_SHORT = 4;
	
	public static final boolean[] DEFAULT_SUGGEST_ADD_SIGNAL = new boolean[] {
			true, true, true, true, true, true, true, true };

	public static final int STRATEGY_CONSERVATIVE = 1;
	public static final int STRATEGY_POSITIVE = 2;

	public static final String CONS_FN = "data/conservative_my.log";
	public static final String POSI_FN = "data/positive_my.log";
	public String finalSuggestion = null;
	public String summary = null;
	private BufferedWriter writer;
	private static Logger DEFAULT_LOGGER = loadDefaultLogger();
	public Logger logger = DEFAULT_LOGGER;

	private static boolean IS_GENERATE_GRID_CSV = false; // 產生累積獲利 CSV 檔 // 約需執行
	private static boolean IS_PRINT_TURTLE_ACTION = true; // 印出每筆進出場記錄
	// private static boolean IS_PRINT_TURTLE_ACTION = false; // 印出每筆進出場記錄

	// 5 分鐘
	// private static boolean IS_GENERATE_GRID_CSV = true; // 產生累積獲利 CSV 檔 //
	// 約需執行 5 分鐘
	/**
	 * 系統強制平倉點數
	 */
	public static int FORCE_STOPLOSS = 100000;
	public static int FORCE_STOPLOSS_CONSERVATIVE = 300;
	public static int FORCE_STOPLOSS_POSITIVE = 200;
	private static int SCALE_DOWN_FACTOR = 100; // 獲利 CSV 檔中數值除以此常數，方便作圖
	// private static int[] LOSS_STOP_RANGE_FOR_LONG = {27,27}; // 做多停損點數實驗區間
	// private static int[] LOSS_STOP_RANGE_FOR_LONG = { 10, 90 }; // 做多停損點數實驗區間
	public static int[] LOSS_STOP_RANGE_FOR_LONG = null;
	public static int[] LOSS_STOP_RANGE_FOR_LONG_CONSERVATIVE = { 30, 30 }; // 做多停損點數實驗區間
	public static int[] LOSS_STOP_RANGE_FOR_LONG_POSITIVE = { 24, 24 }; // 做多停損點數實驗區間

	public static int[] PROFIT_STOP_RANGE_FOR_LONG = null;
	public static int[] PROFIT_STOP_RANGE_FOR_LONG_CONSERVATIVE = { 195, 195 }; // 做多停利點數實驗區間
	public static int[] PROFIT_STOP_RANGE_FOR_LONG_POSITIVE = { 200, 200 }; // 做多停利點數實驗區間

	// private static int[] LOSS_STOP_RANGE_FOR_SHORT = {27,27}; // 做空停損點數實驗區間
	// private static int[] LOSS_STOP_RANGE_FOR_SHORT = { 10, 90 }; //
	// 做空停損點數實驗區間
	public static int[] LOSS_STOP_RANGE_FOR_SHORT = null;
	public static int[] LOSS_STOP_RANGE_FOR_SHORT_CONSERVATIVE = { 55, 55 }; // 做空停損點數實驗區間
	public static int[] LOSS_STOP_RANGE_FOR_SHORT_POSITIVE = { 14, 14 }; // 做空停損點數實驗區間

	public static int[] PROFIT_STOP_RANGE_FOR_SHORT = null;
	public static int[] PROFIT_STOP_RANGE_FOR_SHORT_CONSERVATIVE = { 170, 170 }; // 做空停利點數實驗區間
	public static int[] PROFIT_STOP_RANGE_FOR_SHORT_POSITIVE = { 125, 125 }; // 做空停利點數實驗區間

	// int minDaysIn = 1, maxDaysIn = 100, minDaysOut = 1, maxDaysOut = 100;
	private static int minDaysInForLong = 2, maxDaysInForLong = 3,
			minDaysOutForLong = 2, maxDaysOutForLong = 3;
	private static int minDaysInForShort = 2, maxDaysInForShort = 3,
			minDaysOutForShort = 2, maxDaysOutForShort = 3;

	public static int[][] inAndOut = null;
	public static int[][] inAndOut_CONSERVATIVE = new int[][] { // 特別觀察組合
	{ 2, 9, 2, 5 } };

	public static int[][] inAndOut_POSITIVE = new int[][] { // 特別觀察組合
	{ 3, 9, 2, 6 } };

	public PriceDataRefineSellSystem(int strategyType, String BASE_FILENAME,
			String TX_FILENAME) throws IOException {
		if (strategyType == STRATEGY_POSITIVE) {
			LOSS_STOP_RANGE_FOR_LONG = LOSS_STOP_RANGE_FOR_LONG_POSITIVE;
			LOSS_STOP_RANGE_FOR_SHORT = LOSS_STOP_RANGE_FOR_SHORT_POSITIVE;
			inAndOut = inAndOut_POSITIVE;
			PROFIT_STOP_RANGE_FOR_LONG = PROFIT_STOP_RANGE_FOR_LONG_POSITIVE;
			PROFIT_STOP_RANGE_FOR_SHORT = PROFIT_STOP_RANGE_FOR_SHORT_POSITIVE;
			FORCE_STOPLOSS = FORCE_STOPLOSS_POSITIVE;
			writer = new BufferedWriter(new FileWriter(POSI_FN));
		} else {
			LOSS_STOP_RANGE_FOR_LONG = LOSS_STOP_RANGE_FOR_LONG_CONSERVATIVE;
			LOSS_STOP_RANGE_FOR_SHORT = LOSS_STOP_RANGE_FOR_SHORT_CONSERVATIVE;
			inAndOut = inAndOut_CONSERVATIVE;
			PROFIT_STOP_RANGE_FOR_LONG = PROFIT_STOP_RANGE_FOR_LONG_CONSERVATIVE;
			PROFIT_STOP_RANGE_FOR_SHORT = PROFIT_STOP_RANGE_FOR_SHORT_CONSERVATIVE;
			FORCE_STOPLOSS = FORCE_STOPLOSS_CONSERVATIVE;
			writer = new BufferedWriter(new FileWriter(CONS_FN));
		}

		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		Date today = GregorianCalendar.getInstance().getTime();
		BarSet.ADX_ATTACH = true;
		long startTime = System.currentTimeMillis();

		String filename = BASE_FILENAME;

		FileReader reader = new FileReader(filename);
		BarSet barSet = new BarSet(reader);
		// Chart.draw(barSet);

		String filename2 = TX_FILENAME;
		FileReader reader2 = new FileReader(filename2);
		BarSet barSet2 = new BarSet(reader2);

		// print day records in which range is over 300
		// bigRange(barSet, 300);

		int maxProfitDaysInForLong = 0, maxProfitDaysOutForLong = 0, maxProfitDaysInForShort = 0, maxProfitDaysOutForShort = 0, maxProfitLossStopForLong = LOSS_STOP_RANGE_FOR_LONG[0], maxProfitLossStopForShort = LOSS_STOP_RANGE_FOR_SHORT[0], maxProfitProfitStopForLong = PROFIT_STOP_RANGE_FOR_LONG[0], maxProfitProfitStopForShort = PROFIT_STOP_RANGE_FOR_SHORT[0];
		// csv file for Excel graphing
		if (IS_GENERATE_GRID_CSV) {
			BufferedWriter csvOut = new BufferedWriter(new FileWriter(
					"data/parameter.csv"));
			StringBuilder sb = new StringBuilder();
			StringBuffer buf = new StringBuffer();
			StatCalc scStrategyProfit = new StatCalc(); // 記錄所有進出天數組合的獲利

			int kStep = 7;
			int qStep = 7;
			int oStep = 20;
			int pStep = 20;
			for (int k = LOSS_STOP_RANGE_FOR_LONG[0]; k <= LOSS_STOP_RANGE_FOR_LONG[1]; k += kStep) {
				for (int q = LOSS_STOP_RANGE_FOR_SHORT[0]; q <= LOSS_STOP_RANGE_FOR_SHORT[1]; q += qStep) {
					for (int o = PROFIT_STOP_RANGE_FOR_LONG[0]; o <= PROFIT_STOP_RANGE_FOR_LONG[1]; o += oStep) {
						for (int p = PROFIT_STOP_RANGE_FOR_SHORT[0]; p <= PROFIT_STOP_RANGE_FOR_SHORT[1]; p += pStep) {
							StatCalc stopStrategy = new StatCalc(); // 記錄所有進出天數組合的獲利

							for (int i = minDaysInForLong; i <= maxDaysInForLong; i++) {
								for (int j = minDaysOutForLong; j <= maxDaysOutForLong; j++) {
									for (int m = minDaysInForShort; m <= maxDaysInForShort; m++) {
										for (int n = minDaysOutForShort; n <= maxDaysOutForShort; n++) {

											double profit = turtle(barSet, i,
													j, m, n, k, q, o, p,
													barSet2);
											scStrategyProfit.enter(profit,
													new int[] { i, j, m, n, k,
															q, o, p });
											stopStrategy.enter(profit,
													new int[] { i, j, m, n, k,
															q, o, p });
											// int scaleProfit = (int)(profit /
											// SCALE_DOWN_FACTOR);
											// sb.append(String.format("%d",
											// scaleProfit));
											// if (j != maxDaysOut)
											// sb.append(","); // row end
											// 不加 ,
										}
									}
									System.out.print(".");
								}
							}
							buf
									.append(String
											.format(
													"完成停損%d,%d 停利%d,%d - 最大獲利組合(做多%d,%d)(做空%d,%d)[停%d,%d]=%.2f,最小獲利組合(做多%d,%d)(做空%d,%d)[停%d,%d]=%.2f,平均獲利=%.2f,正獲利組合數=%d(平均%.2f),負獲利組合數=%d(平均%.2f)",
													k,
													q,
													o,
													p,
													stopStrategy.getMaxParam()[0],
													stopStrategy.getMaxParam()[1],
													stopStrategy.getMaxParam()[2],
													stopStrategy.getMaxParam()[3],
													stopStrategy.getMaxParam()[4],
													stopStrategy.getMaxParam()[5],
													stopStrategy.getMax(),
													stopStrategy.getMinParam()[0],
													stopStrategy.getMinParam()[1],
													stopStrategy.getMinParam()[2],
													stopStrategy.getMinParam()[3],
													stopStrategy.getMinParam()[4],
													stopStrategy.getMinParam()[5],
													stopStrategy.getMin(),
													stopStrategy.getMean(),
													stopStrategy
															.getPositiveCount(),
													stopStrategy
															.getPositiveMean(),
													stopStrategy
															.getNegativeCount(),
													stopStrategy
															.getNegativeMean()));
							System.out.println(buf.toString());
							// 完成停損%d,%d 停利%d,%d -
							// 最大獲利組合(做多%d,%d)(做空%d,%d)[停%d,%d]=%.2f,最小獲利組合(做多%d,%d)(做空%d,%d)[停%d,%d]=%.2f,平均獲利=%.2f,正獲利組合數=%d(平均%.2f),負獲利組合數=%d(平均%.2f)
							String outStr = k + "," + q + "," + o + "," + p
									+ "," + stopStrategy.getMaxParam()[0] + ","
									+ stopStrategy.getMaxParam()[1] + ","
									+ stopStrategy.getMaxParam()[2] + ","
									+ stopStrategy.getMaxParam()[3] + ","
									+ stopStrategy.getMaxParam()[4] + ","
									+ stopStrategy.getMaxParam()[5] + ","
									+ stopStrategy.getMax() + ","
									+ stopStrategy.getMinParam()[0] + ","
									+ stopStrategy.getMinParam()[1] + ","
									+ stopStrategy.getMinParam()[2] + ","
									+ stopStrategy.getMinParam()[3] + ","
									+ stopStrategy.getMinParam()[4] + ","
									+ stopStrategy.getMinParam()[5] + ","
									+ stopStrategy.getMin() + ","
									+ stopStrategy.getMean() + ","
									+ stopStrategy.getPositiveCount() + ","
									+ stopStrategy.getPositiveMean() + ","
									+ stopStrategy.getNegativeCount() + ","
									+ stopStrategy.getNegativeMean();
							csvOut.write(outStr + "\n");
							csvOut.flush();
							buf = new StringBuffer();
						}
						// sb.append("\n");
					}
				}
			}
			csvOut.close();
			System.out
					.println(String
							.format(
									"最大獲利組合(做多%d,%d)(做空%d,%d)[停損%d,%d][停利%d,%d]=%.2f,"
											+ "最小獲利組合(做多%d,%d)(做空%d,%d)[停損%d,%d][停利%d,%d]=%.2f,"
											+ "平均獲利=%.2f,正獲利組合數=%d(平均%.2f),負獲利組合數=%d(平均%.2f)",
									scStrategyProfit.getMaxParam()[0],
									scStrategyProfit.getMaxParam()[1],
									scStrategyProfit.getMaxParam()[2],
									scStrategyProfit.getMaxParam()[3],
									scStrategyProfit.getMaxParam()[4],
									scStrategyProfit.getMaxParam()[5],
									scStrategyProfit.getMaxParam()[6],
									scStrategyProfit.getMaxParam()[7],
									scStrategyProfit.getMax(), scStrategyProfit
											.getMinParam()[0], scStrategyProfit
											.getMinParam()[1], scStrategyProfit
											.getMinParam()[2], scStrategyProfit
											.getMinParam()[3], scStrategyProfit
											.getMinParam()[4], scStrategyProfit
											.getMinParam()[5], scStrategyProfit
											.getMinParam()[6], scStrategyProfit
											.getMinParam()[7], scStrategyProfit
											.getMin(), scStrategyProfit
											.getMean(), scStrategyProfit
											.getPositiveCount(),
									scStrategyProfit.getPositiveMean(),
									scStrategyProfit.getNegativeCount(),
									scStrategyProfit.getNegativeMean()));

			maxProfitDaysInForLong = scStrategyProfit.getMaxParam()[0];
			maxProfitDaysOutForLong = scStrategyProfit.getMaxParam()[1];
			maxProfitLossStopForLong = scStrategyProfit.getMaxParam()[2];
			maxProfitLossStopForShort = scStrategyProfit.getMaxParam()[3];
		}

		System.out.println("");
		for (int[] ia : inAndOut) {
			turtle(barSet, ia[0], ia[1], ia[2], ia[3],
					maxProfitLossStopForLong, maxProfitLossStopForShort,
					maxProfitProfitStopForLong, maxProfitProfitStopForShort,
					barSet2);
			System.out.println("");
		}

		// 重新 print 一次最大獲利組合
		/*
		 * if (IS_GENERATE_GRID_CSV) { turtle(barSet, maxProfitDaysInForLong,
		 * maxProfitDaysOutForLong, maxProfitDaysInForShort,
		 * maxProfitDaysOutForShort, maxProfitLossStopForLong,
		 * maxProfitLossStopForShort, maxProfitProfitStopForLong,
		 * maxProfitProfitStopForShort, barSet2); }
		 */
		// Get elapsed time in milliseconds
		long elapsedTimeMillis = System.currentTimeMillis() - startTime;
		System.out.println(String.format("執行時間: %.2f 秒",
				elapsedTimeMillis / 1000F));
		writer.close();
	}

	public static void copyFile(String srcFN, String destFN) {
		try {
			File inputFile = new File(srcFN);
			File outputFile = new File(destFN);

			FileReader in = new FileReader(inputFile);
			FileWriter out = new FileWriter(outputFile);
			int c;

			while ((c = in.read()) != -1)
				out.write(c);

			in.close();
			out.close();
		} catch (IOException e) {
			System.out.println(e);
		}
	}

	public static void bigRange(BarSet barSet, int howBig) {
		ListIterator<Bar> it = barSet.iter();
		int barCountTotal = 0;
		int barCountMatch = 0;
		while (it.hasNext()) {
			Bar bar = it.next();
			barCountTotal++;
			if (bar.range > howBig) {
				System.out.println(bar);
				barCountMatch++;
			}
		}
		System.out.println(String.format("%d out of %d match the criteria",
				barCountMatch, barCountTotal));
	}

	private static int highestIndex(List<Double> list) {
		int ret = 0;
		Iterator<Double> iter = list.iterator();
		double highest = Double.MIN_VALUE;
		int currentIndex = 0;
		while (iter.hasNext()) {
			double currentValue = iter.next();
			if (currentValue > highest) {
				highest = currentValue;
				ret = currentIndex;
			}
			currentIndex++;
		}
		return ret;
	}

	private static int lowestIndex(List<Double> list) {
		int ret = 0;
		Iterator<Double> iter = list.iterator();
		double lowest = Double.MAX_VALUE;
		int currentIndex = 0;
		while (iter.hasNext()) {
			double currentValue = iter.next();
			if (currentValue < lowest) {
				lowest = currentValue;
				ret = currentIndex;
			}
			currentIndex++;
		}
		return ret;
	}

	private static int diffCalendarDays(Bar current, Bar base) {
		long diffMillis = current.today.getTimeInMillis()
				- base.today.getTimeInMillis();
		return (int) (diffMillis / (24 * 60 * 60 * 1000));
	}

	int countxx = 0;
	StringBuffer testBuf = new StringBuffer();

	public double turtle(BarSet barSet, int daysInForLong, int daysOutForLong,
			int daysInForShort, int daysOutForShort, int lossStopForLong,
			int lossStopForShort, int profitStopForLong,
			int profitStopForShort, BarSet barSet2) {

		TurtleAction.daysIn4Long = daysInForLong;
		TurtleAction.daysIn4Short = daysInForShort;
		TurtleAction.daysOut4Long = daysOutForLong;
		TurtleAction.daysOut4Short = daysOutForShort;
		TurtleAction.stopProfit4Long = profitStopForLong;
		TurtleAction.stopProfit4Short = profitStopForShort;
		TurtleAction.stopLoss4Long = lossStopForLong;
		TurtleAction.stopLoss4Short = lossStopForShort;
		TurtleAction.FORCE_OUT_VALUE = this.FORCE_STOPLOSS;
		TurtleAction.HALF_FORCE_OUT_VALUE = this.HALF_FORCE_STOP_LOSS;

		boolean skipNextTrade = false;
		int testNum = 0;
		/* 列出所有的統計訊號 */
		StatCalcSet statSet = new StatCalcSet();
		StatCalc scHoldCalendarDays = new StatCalc();
		StatCalc scHoldTransactionDays = new StatCalc();
		StatCalc testCalc = new StatCalc();
		HashMap<String, Integer> tradeMap = new HashMap<String, Integer>();
		String prevTrade = null;
		ListIterator<Bar> it = barSet.iter();
		ListIterator<Bar> it2 = barSet2.iter();
		Bar baseBar = null;
		int baseBarIndex = 0;

		boolean inHand = false;
		int trade_count = 0;
		double average_inprice = 0;
		boolean bull = false;
		double basePrice = 0.0;
		double basePrice2 = 0.0;
		double accuProfit = 0.0;
		boolean todayForceOut = false;
		int dayInHand = 0;
		boolean tryContinueTrade = false;
		int prevTradeType = -1; /* 0為空單，１為多單 */		
		TurtleAction currentTradeAction = null;
		LinkedList<Double> listHighInForLong = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// high
		// 組成的
		// list，用以評估進場點(做多)
		LinkedList<Double> listLowInForLong = new LinkedList<Double>(); // 以各
		// day
		// bar 的
		// low
		// 組成的
		// list，用以評估進場點(做多)
		LinkedList<Double> listHighOutForLong = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// high
		// 組成的
		// list，用以評估出場點(做多)
		LinkedList<Double> listLowOutForLong = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// low
		// 組成的
		// list，用以評估出場點(做多)
		LinkedList<Double> listCloseInForLong = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// close
		// 組成的
		// list，用以評估進場點(做多)
		LinkedList<Double> listCloseOutForLong = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// close
		// 組成的
		// list，用以評估出場點(做多)

		LinkedList<Double> listHighInForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// high
		// 組成的
		// list，用以評估進場點(做空)
		LinkedList<Double> listLowInForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// low
		// 組成的
		// list，用以評估進場點(做空)
		LinkedList<Double> listHighOutForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// high
		// 組成的
		// list，用以評估出場點(做空)
		LinkedList<Double> listLowOutForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// low
		// 組成的
		// list，用以評估出場點(做空)
		LinkedList<Double> listCloseInForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// close
		// 組成的
		// list，用以評估進場點(做空)
		LinkedList<Double> listCloseOutForShort = new LinkedList<Double>(); // 以各
		// day
		// bar
		// 的
		// close
		// 組成的
		// list，用以評估出場點(做空)
		Bar bar = null;
		Bar bar2 = null;
		while (it.hasNext()) {

			if (todayForceOut) { // 今日進場即強制斷頭出場則不必讀取下一筆,因為資料己被讀取過
				todayForceOut = false;
			} else {
				/* 取得新一天的資料 */
				bar = it.next();
				bar2 = it2.next();
				/* 更新進場點資料 window (做多) */
				if (listHighInForLong.size() == daysInForLong) {
					listHighInForLong.removeFirst();
				}
				if (listLowInForLong.size() == daysInForLong) {
					listLowInForLong.removeFirst();
				}
				if (listCloseInForLong.size() == daysInForLong) {
					listCloseInForLong.removeFirst();
				}
				listHighInForLong.add(bar.high);
				listLowInForLong.add(bar.low);
				listCloseInForLong.add(bar.close);

				/* 更新進場點資料 window (做空) */
				if (listHighInForShort.size() == daysInForShort) {
					listHighInForShort.removeFirst();
				}
				if (listLowInForShort.size() == daysInForShort) {
					listLowInForShort.removeFirst();
				}
				if (listCloseInForShort.size() == daysInForShort) {
					listCloseInForShort.removeFirst();
				}
				listHighInForShort.add(bar.high);
				listLowInForShort.add(bar.low);
				listCloseInForShort.add(bar.close);

				/* 更新出場點資料 window (做多) */
				if (listHighOutForLong.size() == daysOutForLong) {
					listHighOutForLong.removeFirst();
				}
				if (listLowOutForLong.size() == daysOutForLong) {
					listLowOutForLong.removeFirst();
				}
				if (listCloseOutForLong.size() == daysOutForLong) {
					listCloseOutForLong.removeFirst();
				}
				listHighOutForLong.add(bar.high);
				listLowOutForLong.add(bar.low);
				listCloseOutForLong.add(bar.close);

				/* 更新出場點資料 window (做空) */
				if (listHighOutForShort.size() == daysOutForShort) {
					listHighOutForShort.removeFirst();
				}
				if (listLowOutForShort.size() == daysOutForShort) {
					listLowOutForShort.removeFirst();
				}
				if (listCloseOutForShort.size() == daysOutForShort) {
					listCloseOutForShort.removeFirst();
				}
				listHighOutForShort.add(bar.high);
				listLowOutForShort.add(bar.low);
				listCloseOutForShort.add(bar.close);
				

				if (it.nextIndex()-2 >0) {
				  Bar yesBar = barSet.getBar((it.nextIndex()-2));
				  Bar yesBar2 = barSet2.getBar((it2.nextIndex()-2));
				  double profit = 0;
				  double addInPrice = 0;
				  double addOutPrice = 0;
				  if (yesBar.close>(1.01*yesBar2.close)) {					  			  
					  //addInPrice = yesBar2.close;
					  addInPrice = bar2.open;
					  addOutPrice = bar2.close;

					  if (bar2.low - addInPrice < -HALF_FORCE_STOP_LOSS) {
						  if (bar2.open-addInPrice < -HALF_FORCE_STOP_LOSS) {
							  profit = bar2.open - addInPrice;
						  }
						  else {
							  profit = -HALF_FORCE_STOP_LOSS;
						  }
					  }
					  else {
						  profit =  addOutPrice - addInPrice;
					  }						  
				      statSet.enter(StatCalcSet.TURTLE_INDAY_DIFF_TRADE_STAT,profit);				
					  statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,profit);
					  statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,profit);
					  TurtleAddAction addAct = new TurtleAddAction(
								barSet, barSet2, it.nextIndex() - 2);
					  addAct.setDiffTradeADDData(TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN, TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE, 
							                                               TurtleAction.LONG_ACTION);
					  this.writer2TradeFile(addAct.getAdditionActionMessage());
				  }
				  else if (yesBar.close<(0.99*yesBar2.close) ) {
					  addInPrice = bar2.open;
					  //addInPrice = yesBar2.close;
					  addOutPrice = bar2.close;
					  if (addInPrice-bar2.high < -HALF_FORCE_STOP_LOSS) {
						  if (addInPrice-bar2.open < -HALF_FORCE_STOP_LOSS) {
							  profit =addInPrice - bar2.open;
						  }
						  else {
							  profit = -HALF_FORCE_STOP_LOSS;
						  }
					  }
					  else {
						  profit =  addInPrice - addOutPrice;
					  }
					  					 
					 statSet.enter(StatCalcSet.TURTLE_INDAY_DIFF_TRADE_STAT,profit);
					 statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,profit);
					 statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,profit);
					  TurtleAddAction addAct = new TurtleAddAction(
								barSet, barSet2, it.nextIndex() - 2);
					  addAct.setDiffTradeADDData(TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN, TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE, 
							                                               TurtleAction.SHORT_ACTION);
					  this.writer2TradeFile(addAct.getAdditionActionMessage());
				  }
				}
								
			}
				
			//testCalc.enter( bar.close - bar.open);
			if (!inHand) { // 目前空手
				useReverse = false;
				if ((listLowInForShort.size() == daysInForShort && lowestIndex(listLowInForShort) == daysInForShort - 1)
						&& (listHighInForLong.size() == daysInForLong && highestIndex(listHighInForLong) == daysInForLong - 1)) { // 盤中
					// 創
					// daysInForShort
					// 天新低且創
					// daysInForLong
					// 天新高(盤中雙向突破）
					// do nothing, 不進場
					double profit = 0;
					Bar nextBar = barSet.getBar(it.nextIndex());
					Bar nextBar2 = barSet2.getBar(it2.nextIndex());

					TurtleAddAction addAct = new TurtleAddAction(barSet,
							barSet2, it.nextIndex() - 1);
					addAct
					.setADDData(
							TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
							TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
							TurtleAction.SHORT_ACTION,
							null);	
					this
					.writer2TradeFile(addAct
							.getAdditionActionMessage());
					
					if (nextBar2.high - bar2.close > HALF_FORCE_STOP_LOSS) { 
					  if (nextBar2.open - bar2.close >HALF_FORCE_STOP_LOSS) {
						  profit = bar2.close-nextBar2.open;						  
					  }
					  else
						  profit = -HALF_FORCE_STOP_LOSS;		  
					}
					else 
						profit = bar2.close-nextBar2.close;					
					
					statSet
							.enter(StatCalcSet.TURTLE_NON_HOLD_TRADE_STAT,
									profit);
					statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
							profit);
					statSet.enter(
							StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
							profit);			
					/*隔天不進場,則可以不skip*/
					skipNextTrade = false;
					System.out.println("********雙向突破,下一單不跟之策略取消********");
				} else if (listLowInForShort.size() == daysInForShort
						&& lowestIndex(listLowInForShort) == daysInForShort - 1) {
					inHand = true; // (空單)進場
					bull = false; // 建立 short position
					if (prevTrade != null) {
						String d = "空單進場,前單為" + prevTrade;
						if (tradeMap.containsKey(d)) {
							tradeMap.put(d, tradeMap.get(d) + 1);
						} else {
							tradeMap.put(d, 1);
						}
					}
					int nextIndex = it.nextIndex();
					if (nextIndex == barSet.size())
						continue;
                    
					Bar nextBar = barSet.getBar(nextIndex); // 交易 DATA_FILENAME
					Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

					basePrice = nextBar.open; // 假設隔天開盤價成交
					basePrice2 = nextBar2.open; // 假設隔天開盤價成交

					if (nextBar2.high > nextBar2.open+300) {
						/*收盤不進另一半*/
						System.out.println("收盤不加碼!!");
						trade_count = 2;
						average_inprice = nextBar2.open;							
					}
					else if (nextBar.low < bar.low || nextBar.close<nextBar.open) {
						/*收盤再進另一半*/
						trade_count = 4;
						average_inprice = (nextBar2.close+nextBar2.open)/2;
						System.out.println("收盤再加碼!!");
					}
					else {
					  /*收盤不進另一半*/
					  /*實驗結果是,收盤就認賠,其實不會比放著2小單,最後依出場條件出場來得好*/
					  System.out.println("收盤不加碼!!");
					  trade_count = 2;
					  average_inprice = nextBar2.open;
					}
					
                    
					Bar prevBar = barSet.getBar(nextIndex-2); // 交易 DATA_FILENAME
					Bar prevBar2 = barSet2.getBar(nextIndex-2); // 交易
					if (bar.close>bar2.close && bar.close - bar.low <0.15*(bar.high-bar.low)) {
						System.out.println("明天期貨開盤小於今日期貨收盤價的話,收盤再空單進場");						
					}
					if (bar.close>bar2.close && nextBar2.open < bar2.close && bar.close - bar.low <0.15*(bar.high-bar.low)) {
						/*收盤進場*/
						testCalc.enter(nextBar2.close - nextBar2.open);
					}					
					else {
						testCalc.enter(nextBar2.open-nextBar2.close);
					}
					
					if (false) {
					 if (nextBar2.open > bar.close){
						/*開盤進場*/
						//testCalc.enter(nextBar2.open-nextBar2.close);
					 }
					 else if (nextBar2.open < bar2.close) {
						/*開盤進場*/
						//testCalc.enter(nextBar2.open-nextBar2.close);
					 }					
					}
					
					//testCalc.enter(nextBar2.open-nextBar2.close);
					
					int in_type = TurtleAction.SHORT_ACTION;

					TurtleAction act = new TurtleAction(barSet, barSet2,
							nextIndex - 1);					
					if (tryContinueTrade && prevTradeType == STOP_LOSS_SHORT) {
						/* 前單為空單停損出場，則前單不出場，續單, 目前這會賠 --代表反向會賺,但因為要交易成本,不建議~! */
						// statSet.enter(StatCalcSet.KEEP_TRADE_SHORT,
						// nextBar2.open - bar2.close);
						// statSet.enter(StatCalcSet.TURTLE_TOTAL_KEEP_TRADE_STAT,
						// nextBar2.open - bar2.close);
						// System.out.println("收盤作多一口,開盤平倉--獲利不大");
						// in_type = TurtleAction.SHORT_ACTION_KEEP_PREV_TRADE;

						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								nextBar2.open);						
					} else if (tryContinueTrade && prevTradeType == STOP_LOSS_LONG) {
						/* 前單為多單停損出場，來空單進場,則提前放空~! */
						basePrice2 = bar2.close;						
						statSet.enter(StatCalcSet.ADVANCED_TRADE_IN_SHORT,
								bar2.close - nextBar2.open);
						statSet
								.enter(
										StatCalcSet.TURTLE_TOTAL_TRADE_IN_SPECIAL_HANDLE_STAT,
										bar2.close - nextBar2.open);
						//statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT,
						//		bar2.close - nextBar2.open);						
						in_type = TurtleAction.SHORT_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN;

						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								bar2.close);
					}
					else  if (tryContinueTrade && prevTradeType == STOP_PROFIT_LONG) { /*前為多單停利出場,今為空單進場*/
                       /*目前實驗不出什麼結果,可以再看看*/
						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								nextBar2.open);
					}
					else {

						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								nextBar2.open);
					}

					baseBar = nextBar;
					baseBarIndex = it.nextIndex();

					System.out.println("大盤入場參考價:" + basePrice + "," + "期貨入場價:"
							+ basePrice2);

					this.writer2TradeFile(act.getActionMessage());
					currentTradeAction = act;
					
					/* 今日收盤進場放空 */
					/* 今日收盤進場比明日開盤進場好一點點 */
					if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_IN_SHORT] == true) {
						double addInPrice = 0;
						double addOutPrice = 0;
						TurtleAddAction addAct = new TurtleAddAction(barSet,
								barSet2, nextIndex - 1);
						if (in_type == TurtleAction.SHORT_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN) {/* prefer提前放空 */
							addInPrice = bar2.close;
							addAct
									.setADDData(
											TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
											TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
											TurtleAction.SHORT_ACTION,
											currentTradeAction);
						} else {
							addInPrice = nextBar2.open;
							addAct
									.setADDData(
											TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
											TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
											TurtleAction.SHORT_ACTION,
											currentTradeAction);
						}
						addOutPrice = nextBar2.close;

						this
								.writer2TradeFile(addAct
										.getAdditionActionMessage());

						double profit = 0;
						if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
							if (nextBar2.open - addInPrice > HALF_FORCE_STOP_LOSS) {
								profit = addInPrice - nextBar2.open;
							} else {
								profit = -HALF_FORCE_STOP_LOSS;
							}
						} else {
							profit = addInPrice - addOutPrice;
						}

						statSet.enter(StatCalcSet.IN_SIGNAL_ALL_InDay, profit);
						statSet
								.enter(StatCalcSet.IN_SIGNAL_SHORT_InDay,
										profit);
						statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
								profit);
						statSet.enter(
								StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
								profit);
					}
				} else if (listHighInForLong.size() == daysInForLong
						&& highestIndex(listLowInForLong) == daysInForLong - 1) {
							
					inHand = true; // 進場
					bull = true; // 建立 long position
					if (prevTrade != null) {
						String d = "多單進場,前單為" + prevTrade;
						if (tradeMap.containsKey(d)) {
							tradeMap.put(d, tradeMap.get(d) + 1);
						} else {
							tradeMap.put(d, 1);
						}
					}
					int nextIndex = it.nextIndex();
					if (nextIndex == barSet.size())
						continue;

                    if (false && bar.volume > 200000) { /*未找出合理的式子*/
                    	Bar yesBar = barSet.getBar(nextIndex-2);
                    	Bar yesBar2 = barSet2.getBar(nextIndex-2);
                    	Bar yesyesBar = barSet.getBar(nextIndex-3);
    					Bar nextBar = barSet.getBar(nextIndex);
    					Bar nextBar2 = barSet2.getBar(nextIndex);                    	
                    	//if (yesBar.volume > 220000 && yesyesBar.volume>200000) {
                    	//if (yesBar.volume>200000 && bar.volume > yesBar.volume && yesBar.volume>yesyesBar.volume) {
                    	//if (yesBar.volume>200000 && yesyesBar.volume>200000 && nextBar2.open>bar2.close) {
    					if (yesBar.volume > 200000 && bar.volume > yesBar.volume && bar2.close > bar.close && bar2.high > bar.high) {
                    	  System.out.println("不建議");
    					  //useReverse = true;
                    	  //bull = false;
                    	}
                    }			
                    
					Bar nextBar = barSet.getBar(nextIndex);
					Bar nextBar2 = barSet2.getBar(nextIndex);

					basePrice = nextBar.close; // 假設隔天收盤價成交 // 判斷進出場價
					basePrice2 = nextBar2.open; // 假設隔天收盤價成交 // 實際操作價

					Bar prevBar = barSet.getBar(nextIndex-2);
					Bar prevBar2 = barSet2.getBar(nextIndex-2);
					
					
					if (prevTrade != null && prevTrade.equals("多單,停利出場")) {
						if (bar2.close < bar2.open && bar2.close<prevBar2.close) {
							System.out.println("今收黑,且今為開低,則明日請收盤再進場, 這種場合必輸XD");
							//testCalc.enter(nextBar2.close-nextBar2.open);							
						}
						else {
							if (bar2.close < bar2.open && nextBar2.open < bar2.close) {
								//testCalc.enter(nextBar2.close-nextBar2.open);
							}
							//testCalc.enter(nextBar2.close-nextBar2.open);
							if (nextBar2.low < 0.995*nextBar2.open) {
								//testCalc.enter(-0.005*nextBar2.open);
							}
							else {
								//testCalc.enter(nextBar2.close-nextBar2.open);
							}
						}
					}					
					
					
					
					if (nextBar2.low < nextBar2.open-300) {
						/*收盤不進另一半*/
						System.out.println("收盤不加碼!!");
						trade_count = 2;
						average_inprice = nextBar2.open;							
					}
					else if (nextBar.close>nextBar.open || nextBar.close > bar.low) {
						/*收盤再進另一半*/
						System.out.println("收盤再加碼!!");
						trade_count = 4;
						average_inprice = (nextBar2.close+nextBar2.open)/2;
					}
					else {
						 System.out.println("收盤不加碼!!");
 					     trade_count = 2;
						 average_inprice = nextBar2.open;
						 //testCalc.enter(nextBar2.close-nextBar2.open);
					}
					
					TurtleAction act = new TurtleAction(barSet, barSet2,
							nextIndex - 1);
					int in_type = TurtleAction.LONG_ACTION;
					if (tryContinueTrade && prevTradeType == STOP_LOSS_LONG) {
						/* 前單為多單停損出場，同向多單再進場，則前單不出場，續單 */
						basePrice2 = bar2.close;
						statSet.enter(StatCalcSet.KEEP_TRADE_LONG,
								nextBar2.open - bar2.close);
						statSet
								.enter(
										StatCalcSet.TURTLE_TOTAL_TRADE_IN_SPECIAL_HANDLE_STAT,
										nextBar2.open - bar2.close);
						//statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT,
						//		nextBar2.open - bar2.close);												
						in_type = TurtleAction.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN;
						System.out
								.println("***今天收盤多單進場,隔日開盤平倉,winner ratio=0.64,平均獲利20點(去頭尾平均=13)");
						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								bar2.close);
					} else if (tryContinueTrade && prevTradeType == STOP_LOSS_SHORT) {
						/* 前單為空單停損出場，來多單進場,則提前作多~不prefer,沒什麼好處 */
						// statSet.enter(StatCalcSet.ADVANCED_TRADE_IN_LONG,
						// nextBar2.open - bar2.close);
						// statSet.enter(StatCalcSet.TURTLE_TOTAL_TRADE_IN_HANDLE_STAT,
						// nextBar2.open - bar2.close);
						// in_type=
						// TurtleAction.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN;
						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								nextBar2.open);
					}
					else {
						act.setData(TurtleAction.IN_ACTION, in_type, -1, -1,
								nextBar2.open);
					}

					baseBar = nextBar;
					baseBarIndex = it.nextIndex();
					System.out.println("大盤入場參考價:" + basePrice + "," + "期貨入場價:"
							+ basePrice2);

					
					this.writer2TradeFile(act.getActionMessage());
					currentTradeAction = act;

					if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_IN_LONG] == true) {
						double addInPrice = 0;
						double addOutPrice = 0;
						TurtleAddAction addAct = new TurtleAddAction(barSet,
								barSet2, nextIndex - 1);

						if (in_type == TurtleAction.LONG_ACTION_KEEP_PREV_TRADE_OR_ADVANCED_IN) {
							addInPrice = bar2.close;
							addAct
									.setADDData(
											TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
											TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
											TurtleAction.LONG_ACTION,
											currentTradeAction);
						} else {
							addInPrice = nextBar2.open;
							addAct
									.setADDData(
											TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
											TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
											TurtleAction.LONG_ACTION,
											currentTradeAction);
						}
						addOutPrice = nextBar2.close;

						this
								.writer2TradeFile(addAct
										.getAdditionActionMessage());

						double profit = 0;
						if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
							if (addInPrice - nextBar2.open > HALF_FORCE_STOP_LOSS) {
								profit = nextBar2.open - addInPrice;
							} else {
								profit = -HALF_FORCE_STOP_LOSS;
							}
						} else {
							profit = addOutPrice - addInPrice;
						}

						statSet.enter(StatCalcSet.IN_SIGNAL_ALL_InDay, profit);
						statSet.enter(StatCalcSet.IN_SIGNAL_LONG_InDay, profit);
						statSet.enter(StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
								profit);
						statSet.enter(
								StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
								profit);
					}
				}

				/* 今日沒有入場,則之前有續單要求都不會成立 */
				tryContinueTrade = false;
				prevTradeType = -1;
			} else {
				// 目前手上有部位
				/* 昨天叫你進場，結果今天開盤進場,盤中就可能遇到行情超過預期,當天就被停損出場 */
				if (bar2.high >= basePrice2 + FORCE_STOPLOSS // 強制盤中停損
						&& !bull) { // 手上持有 short position
					boolean open_out = false;
					todayForceOut = true;
					inHand = false; // 出場
					prevTrade = "空單,強制盤中停損出場";
					int nextIndex = it.nextIndex();
					if (nextIndex == barSet.size())
						continue;
					double liquidatePrice2 = basePrice2 + FORCE_STOPLOSS;

					/**
					 * 開盤就要被強迫平倉了
					 */
					if (bar2.open >= basePrice2 + FORCE_STOPLOSS) { /* 應該不會有這種情況 */
						liquidatePrice2 = bar2.open;
						open_out = true;
					}
					Bar nextBar = barSet.getBar(nextIndex - 1); // 今天就交易
					Bar nextBar2 = barSet2.getBar(nextIndex - 1); // 今天就交易

					double profit2 = basePrice2 - liquidatePrice2; // 計算獲利

					TurtleAction act = new TurtleAction(barSet, barSet2,
							nextIndex - 1);
					if (open_out) {
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.SHORT_ACTION,
								TurtleAction.FORCE_STOP_LOSS_TODAY_REASON,
								TurtleAction.OUT_ACTION_AT_START,
								liquidatePrice2);
					} else {
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.SHORT_ACTION,
								TurtleAction.FORCE_STOP_LOSS_TODAY_REASON,
								TurtleAction.OUT_ACTION_AT_INSTANT,
								liquidatePrice2);
					}
					this.writer2TradeFile(act.getActionMessage());

					scHoldCalendarDays
							.enter(diffCalendarDays(nextBar, baseBar));
					scHoldTransactionDays.enter(it.nextIndex() - 1
							- baseBarIndex);

					statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
					statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, false);
					if (skipNextTrade ==true) {
						statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
						statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
					}
					
					if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
						skipNextTrade = true;
						System.out.println("********如不是雙向突破,則下一單不跟********");
					}
					else {
						skipNextTrade = false;
					}
					statSet.enter(StatCalcSet.TURTLE_TOTAL_SHORT_STAT, profit2);
					statSet.enter(StatCalcSet.FORCE_LOSS_ALL_OUT, profit2);
					statSet.enter(StatCalcSet.FORCE_LOSS_SHORT_OUT, profit2);

				} else if (bar2.low <= basePrice2 - FORCE_STOPLOSS // 強制盤中停損
						&& bull) { // 手上持有 多單
					boolean open_out = false;
					todayForceOut = true;
					inHand = false; // 出場
					prevTrade = "多單,強制盤中停損出場";
					int nextIndex = it.nextIndex();
					if (nextIndex == barSet.size())
						continue; // 解決在資料尾端會造成 IndexOutOfBoundsException 的問題
					double liquidatePrice2 = basePrice2 - FORCE_STOPLOSS;
					/**
					 * 開盤就要被強迫平倉了
					 */
					if (bar2.open <= basePrice2 - FORCE_STOPLOSS) { /* 應沒這種情況 */
						liquidatePrice2 = bar2.open;
						open_out = true;
					}
					Bar nextBar = barSet.getBar(nextIndex - 1); // 交易
					Bar nextBar2 = barSet2.getBar(nextIndex - 1); // 交易

					double profit2 = liquidatePrice2 - basePrice2; // 計算獲利

					TurtleAction act = new TurtleAction(barSet, barSet2,
							nextIndex - 1);
					if (open_out) {
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.LONG_ACTION,
								TurtleAction.FORCE_STOP_LOSS_AT_START_REASON,
								TurtleAction.OUT_ACTION_AT_START,
								liquidatePrice2);
					} else {
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.LONG_ACTION,
								TurtleAction.FORCE_STOP_LOSS_REASON,
								TurtleAction.OUT_ACTION_AT_INSTANT,
								liquidatePrice2);
					}
					this.writer2TradeFile(act.getActionMessage());

					scHoldCalendarDays
							.enter(diffCalendarDays(nextBar, baseBar));
					scHoldTransactionDays.enter(it.nextIndex() - baseBarIndex);

					statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
					statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, true);
					
					if (skipNextTrade ==true) {
						statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
						statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
					}
					if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
						skipNextTrade = true;
						System.out.println("********如不是雙向突破,則下一單不跟********");
					}
					else {
						skipNextTrade = false;
					}
					statSet.enter(StatCalcSet.TURTLE_TOTAL_LONG_STAT, profit2);
					statSet.enter(StatCalcSet.FORCE_LOSS_ALL_OUT, profit2);
					statSet.enter(StatCalcSet.FORCE_LOSS_LONG_OUT, profit2);
				}

				else {
					/*
					 * 程式logic: 因為最新的明天資料，是從最新的今日資科copy來的，而在隔天才會被真正的當日資料給replace
					 * 所以如果今日沒被強制停損出場，當下你是看不到明日強制出場的，也就是當天可能會認為 隔天沒訊號或有其它正常出場訊號
					 * 而當明天資料被正確update時，你就知道可能已被清出場啦
					 * 所以我們要先check是否有被強制出場，再看是否有出場訊號． 但如果今天已出現隔天出場條件, 也都可能會有
					 * 隔天中途被迫平倉出場.. 如程式是建議開盤出場的，那就應該要開盤就出場，不會看到強迫停損出場．
					 * 
					 * 目前考慮如果昨天已決定今天要出場，且為盤末出場，則停損價換小(後來取消)
					 */
					boolean alread_out = false;
					if (it2.nextIndex() == barSet2.size())
						continue;
					Bar newbar2 = barSet2.getBar(it2.nextIndex());
					if (newbar2.high >= basePrice2 + FORCE_STOPLOSS // 強制盤中停損
							&& !bull) { // 手上持有 short position
						int decide_force_out = -1; // ==0/1,代表昨天應該已建議今天要出場
						int acttype = -1;
						if (highestIndex(listHighOutForShort) == daysOutForShort - 1) {
							acttype = this.ADD_ACTION_OUT_TRENDREVERSE_SHORT;
							if (DEFAULT_START_OR_NOT[5] == OUT_TRADE_AT_START) {
								// 應採"趨勢反轉出場"出場，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;
							}
						} else if (bar.close >= basePrice + lossStopForShort) // 停損
						{
							acttype = this.ADD_ACTION_OUT_STOPLOSS_SHORT;
							if (DEFAULT_START_OR_NOT[1] == OUT_TRADE_AT_START) {
								// 空單停損，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;
							}
						} else if (bar.close <= basePrice - profitStopForShort) {
							acttype = this.ADD_ACTION_OUT_STOPPROFIT_SHORT;
							if (DEFAULT_START_OR_NOT[3] == OUT_TRADE_AT_START) {
								// 空單停利，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;
							}
						}

						if (decide_force_out != 0) { // ==0則選擇開盤出場,
							// 就會由相對應的出場訊號處理加碼單

							alread_out = true;

							boolean open_out = false;
							int original_force_stoploss = FORCE_STOPLOSS;
							if (decide_force_out == 1) { // 昨日已有建議出場，則今天的停損價要變小
								// FORCE_STOPLOSS = HALF_FORCE_STOP_LOSS;
								FORCE_STOPLOSS = FORCE_STOPLOSS;
							}

							inHand = false; // 出場
							prevTrade = "空單,強制盤中停損出場";
							int nextIndex = it.nextIndex();
							if (nextIndex == barSet.size())
								continue;

							double liquidatePrice2 = basePrice2
									+ FORCE_STOPLOSS;
							/**
							 * 開盤就要被強迫平倉了
							 */
							if (newbar2.open >= basePrice2 + FORCE_STOPLOSS) {
								liquidatePrice2 = newbar2.open;
								open_out = true;
							} else if (newbar2.high <= basePrice2
									+ FORCE_STOPLOSS) {
								assert (true);
							}

							Bar nextBar = barSet.getBar(nextIndex); // 交易
							Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

							TurtleAction act = new TurtleAction(barSet,
									barSet2, nextIndex - 1);
							if (open_out) {
								act
										.setData(
												TurtleAction.OUT_ACTION,
												TurtleAction.SHORT_ACTION,
												TurtleAction.FORCE_STOP_LOSS_AT_START_REASON,
												TurtleAction.OUT_ACTION_AT_START,
												liquidatePrice2);
							} else {
								act.setData(TurtleAction.OUT_ACTION,
										TurtleAction.SHORT_ACTION,
										TurtleAction.FORCE_STOP_LOSS_REASON,
										TurtleAction.OUT_ACTION_AT_INSTANT,
										liquidatePrice2);
							}
							this.writer2TradeFile(act.getActionMessage());

							double profit2 = basePrice2 - liquidatePrice2; // 計算獲利
							scHoldCalendarDays.enter(diffCalendarDays(nextBar,
									baseBar));
							scHoldTransactionDays.enter(it.nextIndex()
									- baseBarIndex);

							statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT,
									profit2);
							statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, false);							
							if (skipNextTrade ==true) {
								statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
								statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
							}
							if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
								skipNextTrade = true;
								System.out.println("********如不是雙向突破,則下一單不跟********");
							}
							else {
								skipNextTrade = false;
							}
							statSet.enter(StatCalcSet.TURTLE_TOTAL_SHORT_STAT,
									profit2);
							statSet.enter(StatCalcSet.FORCE_LOSS_ALL_OUT,
									profit2);
							statSet.enter(StatCalcSet.FORCE_LOSS_SHORT_OUT,
									profit2);

							if (decide_force_out == 1) {
								/* 空單為收盤出場,則前日會建議同向空單加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								TurtleAddAction addAct = new TurtleAddAction(
										barSet, barSet2, nextIndex - 1);
								if (acttype == this.ADD_ACTION_OUT_STOPLOSS_SHORT) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPLOSS_SHORT] == true) {
										addInPrice = bar2.close;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.SHORT_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								} else if (acttype == this.ADD_ACTION_OUT_STOPPROFIT_SHORT) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPPROFIT_SHORT] == true) {
										addInPrice = nextBar2.open;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.SHORT_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								} else if (acttype == this.ADD_ACTION_OUT_TRENDREVERSE_SHORT) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_TRENDREVERSE_SHORT] == true) {
										addInPrice = nextBar2.open;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.SHORT_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								}

								double profit = 0;
								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addInPrice - addOutPrice;
								}

								statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
										profit);
								statSet.enter(
										StatCalcSet.OUT_SIGNAL_SHORT_InDay,
										profit);
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
												profit);
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);

								switch (acttype) {
								case ADD_ACTION_OUT_STOPLOSS_SHORT:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_STOP_LOSS_SHORT_InDay,
													profit);
									break;
								case ADD_ACTION_OUT_STOPPROFIT_SHORT:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_STOP_PROFIT_SHORT_InDay,
													profit);
									break;
								case ADD_ACTION_OUT_TRENDREVERSE_SHORT:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_TREND_REVERSE_SHORT_InDay,
													profit);
									break;
								default:
									assert (true);
								}
							}
							FORCE_STOPLOSS = original_force_stoploss;
						}
					} else if (newbar2.low <= basePrice2 - FORCE_STOPLOSS // 強制盤中停損
							&& bull) { // 手上持有 多單
						int decide_force_out = -1;
						int acttype = -1;
						if (lowestIndex(listLowOutForLong) == daysOutForLong - 1) {
							acttype = this.ADD_ACTION_OUT_TRENDREVERSE_LONG;
							if (DEFAULT_START_OR_NOT[4] == OUT_TRADE_AT_START) {
								// 應採"趨勢反轉出場"出場，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;
							}
						} else if (bar.close <= basePrice - lossStopForLong // 停損
								&& bull) {
							acttype = this.ADD_ACTION_OUT_STOPLOSS_LONG;
							if (DEFAULT_START_OR_NOT[0] == OUT_TRADE_AT_START) {
								// 多單停損，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;
							}
						} else if (bar.close >= basePrice + profitStopForLong // 停利
								&& bull) {
							acttype = this.ADD_ACTION_OUT_STOPPROFIT_LONG;
							if (DEFAULT_START_OR_NOT[2] == OUT_TRADE_AT_START) {
								// 多單停利，且在開盤出場
								decide_force_out = 0;
							} else {
								decide_force_out = 0;

							}
						}

						if (decide_force_out != 0) { // ==0則選擇開盤出場,
							// 就會由相對應的出場訊號處理加碼單
							int original_force_stoploss = FORCE_STOPLOSS;
							if (decide_force_out == 1) {// 昨日已有建議出場，則今天的停損價要變小
								// FORCE_STOPLOSS = HALF_FORCE_STOP_LOSS;
								FORCE_STOPLOSS = FORCE_STOPLOSS;
							}

							boolean open_out = false;
							inHand = false; // 出場
							prevTrade = "多單,強制盤中停損出場";
							int nextIndex = it.nextIndex();
							if (nextIndex == barSet.size())
								continue; // 解決在資料尾端會造成
							double liquidatePrice2 = basePrice2
									- FORCE_STOPLOSS;

							/**
							 * 開盤就要被強迫平倉了,多單很容易有這個情況,要考慮一下有沒有機會改進
							 */
							if (newbar2.open <= basePrice2 - FORCE_STOPLOSS) {
								liquidatePrice2 = newbar2.open;
								open_out = true;
							} else if (newbar2.low >= basePrice2
									- FORCE_STOPLOSS) {
								assert (true);
							}

							Bar nextBar = barSet.getBar(nextIndex); // 交易
							Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

							TurtleAction act = new TurtleAction(barSet,
									barSet2, nextIndex - 1);
							if (open_out) {
								act
										.setData(
												TurtleAction.OUT_ACTION,
												TurtleAction.LONG_ACTION,
												TurtleAction.FORCE_STOP_LOSS_AT_START_REASON,
												TurtleAction.OUT_ACTION_AT_START,
												liquidatePrice2);
							} else {
								act.setData(TurtleAction.OUT_ACTION,
										TurtleAction.LONG_ACTION,
										TurtleAction.FORCE_STOP_LOSS_REASON,
										TurtleAction.OUT_ACTION_AT_INSTANT,
										liquidatePrice2);
							}
							this.writer2TradeFile(act.getActionMessage());

							double profit2 = liquidatePrice2 - basePrice2; // 計算獲利

							scHoldCalendarDays.enter(diffCalendarDays(nextBar,
									baseBar));
							scHoldTransactionDays.enter(it.nextIndex()
									- baseBarIndex);

							statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT,
									profit2);
							statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, true);							
							if (skipNextTrade ==true) {
								statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
								statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
							}
							if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
								skipNextTrade = true;
								System.out.println("********如不是雙向突破,則下一單不跟********");
							}
							else {
								skipNextTrade = false;
							}
							statSet.enter(StatCalcSet.TURTLE_TOTAL_LONG_STAT,
									profit2);
							statSet.enter(StatCalcSet.FORCE_LOSS_ALL_OUT,
									profit2);
							statSet.enter(StatCalcSet.FORCE_LOSS_LONG_OUT,
									profit2);

							alread_out = true;

							if (decide_force_out == 1) {
								/* 多單為收盤出場,則前日會建議同向多單加碼進場 */

								double addInPrice = 0;
								double addOutPrice = 0;
								TurtleAddAction addAct = new TurtleAddAction(
										barSet, barSet2, nextIndex - 1);
								if (acttype == this.ADD_ACTION_OUT_STOPLOSS_LONG) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPLOSS_LONG] == true) {
										addInPrice = nextBar2.open;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.LONG_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								} else if (acttype == this.ADD_ACTION_OUT_STOPPROFIT_LONG) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPPROFIT_LONG] == true) {
										addInPrice = nextBar2.open;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.LONG_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								} else if (acttype == this.ADD_ACTION_OUT_TRENDREVERSE_LONG) {
									if (DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_TRENDREVERSE_LONG] == true) {
										addInPrice = nextBar2.open;
										addOutPrice = nextBar2.close;
										addAct
												.setADDData(
														TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
														TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
														TurtleAction.LONG_ACTION,
														currentTradeAction);
										this.writer2TradeFile(addAct
												.getAdditionActionMessage());
									}
								}

								double profit = 0;
								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}

								statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
										profit);
								statSet.enter(
										StatCalcSet.OUT_SIGNAL_LONG_InDay,
										profit);
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
												profit);
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);

								switch (acttype) {
								case ADD_ACTION_OUT_STOPLOSS_LONG:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_STOP_LOSS_LONG_InDay,
													profit);
									break;
								case ADD_ACTION_OUT_STOPPROFIT_LONG:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_STOP_PROFIT_LONG_InDay,
													profit);
									break;
								case ADD_ACTION_OUT_TRENDREVERSE_LONG:
									statSet
											.enter(
													StatCalcSet.OUT_SIGNAL_TREND_REVERSE_LONG_InDay,
													profit);
									break;
								default:
									assert (true);
								}
							}
							FORCE_STOPLOSS = original_force_stoploss;
						}
					}

					/* 出場訊號出現當天,沒被清出場的話,正確執行之~(包含一半的停損價的執行) */
					if (alread_out == true) {
						;
					} else if (listHighOutForShort.size() == daysOutForShort
							&& highestIndex(listHighOutForShort) == daysOutForShort - 1
							&& !bull) { // 手上持有 short position
						inHand = false; // (空單)出場
						prevTrade = "空單,趨勢反轉出場";

						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[5] == OUT_TRADE_AT_START ? true
								: false;
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交(多單平倉)
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交(多單平倉)

						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.SHORT_ACTION,
								TurtleAction.TREND_REVERT_REASON,
								startOrEnd ? TurtleAction.OUT_ACTION_AT_START
										: TurtleAction.OUT_ACTION_AT_END,
								liquidatePrice2);
						this.writer2TradeFile(act.getActionMessage());

						double profit2 = basePrice2 - liquidatePrice2; // 計算獲利

						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, false);						
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_SHORT_STAT,
								profit2);
						statSet.enter(StatCalcSet.TREND_REVERSE_ALL_OUT,
								profit2);
						statSet.enter(StatCalcSet.TREND_REVERSE_SHORT_OUT,
								profit2);

						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_TRENDREVERSE_SHORT] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								// addInPrice = nextBar2.open;
								addInPrice = bar2.close;
								// addOutPrice = nextBar2.close;
								addOutPrice = nextBar2.open;
								// act.setADDData(TurtleAction.ADDTRADE_IN_TOMORROW_OPEN,
								// TurtleAction.ADDTRADE_OUT_TOMORROW_CLOSE,
								// TurtleAction.LONG_ACTION);
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
												TurtleAction.LONG_ACTION, act);

								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								profit = addInPrice - addOutPrice;

								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION,
												currentTradeAction);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addInPrice - addOutPrice;
								}

								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_SHORT_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_TREND_REVERSE_SHORT_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}

					} else if (listLowOutForLong.size() == daysOutForLong
							&& lowestIndex(listLowOutForLong) == daysOutForLong - 1
							&& bull) { // 手上持有 long position
						inHand = false; // 出場
						boolean prevStopLoss = (prevTrade != null && prevTrade.equals("多單,停損出場")) ? true : false;
						prevTrade = "多單,趨勢反轉出場";

						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[4] == OUT_TRADE_AT_START ? true
								: false;
						
						//testCalc.enter(nextBar2.close-nextBar2.open);
						
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交(多單平倉)
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交(多單平倉)
						
						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.LONG_ACTION,
								TurtleAction.TREND_REVERT_REASON,
								startOrEnd ? TurtleAction.OUT_ACTION_AT_START
										: TurtleAction.OUT_ACTION_AT_END,
								liquidatePrice2);
						this.writer2TradeFile(act.getActionMessage());
						
						double profit2 = liquidatePrice2 - basePrice2; // 計算獲利

						if (basePrice == bar.close && bar2.close-bar2.open<-150) {
							//System.out.println("今天");
							//testCalc.enter(nextBar2.open-nextBar2.close);
						}
						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, true);						
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_LONG_STAT,
								profit2);
						statSet.enter(StatCalcSet.TREND_REVERSE_ALL_OUT,
								profit2);
						statSet.enter(StatCalcSet.TREND_REVERSE_LONG_OUT,
								profit2);

						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_TRENDREVERSE_LONG] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addInPrice - addOutPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.LONG_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_LONG_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_TREND_REVERSE_LONG_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}
					} else if (bar.close >= basePrice + lossStopForShort // 停損
							&& !bull) { // 手上持有 short position = 做空
						inHand = false; // 出場
						prevTrade = "空單,停損出場";

						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[1] == OUT_TRADE_AT_START ? true
								: false;
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交

						Bar prevBar = barSet.getBar(nextIndex - 2); // 交易
						Bar prevBar2 = barSet2.getBar(nextIndex - 2); // 交易
						if (bar.close==bar.high && bar.close - prevBar.close > 100) {
							//System.out.println("今天");
							//testCalc.enter(nextBar2.open-nextBar2.close);
						}
						if (false) { /* 尚在實驗中,還未try出沒overfitting,結果不錯的參數 */
							if (prevBar.high < prevBar2.high
									&& bar2.high < bar.high) {
								testBuf.append(nextBar2.close - nextBar2.open
										+ "," + bar.mergeBar(bar2) + "\n");
								startOrEnd = true;
								liquidatePrice2 = nextBar2.open;
							} else {
								startOrEnd = false;
								liquidatePrice2 = nextBar2.close;
							}
							System.out.println(testBuf.toString());
						}

						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);

						if (startOrEnd == false) {/*
															 * 空單停損死撐到最後不強迫出場，獲利增300點
															 * 但~~停損是美德~~
															 * 避免價格衝擊才是王道!
															 */
							if (nextBar2.high - basePrice2 >= FORCE_STOPLOSS) {
								if (newbar2.open >= basePrice2 + FORCE_STOPLOSS) {
									liquidatePrice2 = nextBar2.open;
									act
											.setData(
													TurtleAction.OUT_ACTION,
													TurtleAction.SHORT_ACTION,
													TurtleAction.FORCE_STOP_LOSS_AT_START_REASON,
													TurtleAction.OUT_ACTION_AT_START,
													liquidatePrice2);
								} else {
									liquidatePrice2 = basePrice2
											+ FORCE_STOPLOSS;
									act
											.setData(
													TurtleAction.OUT_ACTION,
													TurtleAction.SHORT_ACTION,
													TurtleAction.FORCE_STOP_LOSS_REASON,
													TurtleAction.OUT_ACTION_AT_INSTANT,
													liquidatePrice2);
								}
							} else {
								act
										.setData(
												TurtleAction.OUT_ACTION,
												TurtleAction.SHORT_ACTION,
												TurtleAction.STOP_LOSS_REASON,
												startOrEnd ? TurtleAction.OUT_ACTION_AT_START
														: TurtleAction.OUT_ACTION_AT_END,
												liquidatePrice2);
							}
						} else {
							act
									.setData(
											TurtleAction.OUT_ACTION,
											TurtleAction.SHORT_ACTION,
											TurtleAction.STOP_LOSS_REASON,
											startOrEnd ? TurtleAction.OUT_ACTION_AT_START
													: TurtleAction.OUT_ACTION_AT_END,
											liquidatePrice2);
						}

						this.writer2TradeFile(act.getActionMessage());

						double profit2 = basePrice2 - liquidatePrice2; // 計算獲利

						if (!startOrEnd && profit2 > -100000) {
							/* 不論現在損益，只要下一單是隔天且同向多單，則續抱 */
							/* 這為空單則會賠!!!,所以空單停損不考慮留單 */
							tryContinueTrade = true; /* 可試著保有單 */
							prevTradeType = STOP_LOSS_SHORT;
						} else {
							tryContinueTrade = false;
						}

						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, false);						
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_SHORT_STAT,
								profit2);
						statSet.enter(StatCalcSet.STOP_LOSS_ALL_OUT, profit2);
						statSet.enter(StatCalcSet.STOP_LOSS_SHORT_OUT, profit2);
						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPLOSS_SHORT] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.LONG_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								// addInPrice = nextBar2.open;
								addInPrice = bar2.close;
								addOutPrice = nextBar2.close;
								// act.setADDData(TurtleAction.ADDTRADE_IN_TOMORROW_OPEN,
								// TurtleAction.ADDTRADE_OUT_TOMORROW_CLOSE,
								// TurtleAction.SHORT_ACTION);
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									if (nextBar2.open - addInPrice > HALF_FORCE_STOP_LOSS) {
										profit = addInPrice - nextBar2.open;
									} else {
										profit = -HALF_FORCE_STOP_LOSS;
									}
								} else {
									profit = addInPrice - addOutPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_SHORT_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_STOP_LOSS_SHORT_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}
					} else if (bar.close <= basePrice - lossStopForLong // 停損
							&& bull) { // 手上持有 long position = 做多
						inHand = false; // 出場
						boolean prevStopLoss = (prevTrade != null && prevTrade.equals("多單,停損出場")) ? true : false;
						prevTrade = "多單,停損出場";

						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[0] == OUT_TRADE_AT_START ? true
								: false;

						
						{ 
							
							if (dayInHand ==5) {
								System.out.println(bar.mergeBar(bar2));
								//testCalc.enter(bar2.close-nextBar2.close);
							}
							else {
								//testCalc.enter(nextBar2.close-nextBar2.close);
							}
						}
						
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交(多單平倉)
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交(多單平倉)
						
						if (prevStopLoss == true) {
							//System.out.println("今天");
							//testCalc.enter((nextBar2.close-bar2.close));
						}
						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);

						if (startOrEnd == false) { /*
															 * 多單停損死撐到最後不強迫出場，獲利增1000點
															 * 但~~停損是美德~~
															 * 避免價格衝擊才是王道! 
															 */
							if (nextBar2.low <= basePrice2 - FORCE_STOPLOSS) {
								if (nextBar2.open <= basePrice2
										- FORCE_STOPLOSS) {
									liquidatePrice2 = nextBar2.open;
									act
											.setData(
													TurtleAction.OUT_ACTION,
													TurtleAction.LONG_ACTION,
													TurtleAction.FORCE_STOP_LOSS_AT_START_REASON,
													TurtleAction.OUT_ACTION_AT_START,
													liquidatePrice2);
								} else {
									liquidatePrice2 = basePrice2
											- FORCE_STOPLOSS;
									act
											.setData(
													TurtleAction.OUT_ACTION,
													TurtleAction.LONG_ACTION,
													TurtleAction.FORCE_STOP_LOSS_REASON,
													TurtleAction.OUT_ACTION_AT_INSTANT,
													liquidatePrice2);
								}
							} else {
								act
										.setData(
												TurtleAction.OUT_ACTION,
												TurtleAction.LONG_ACTION,
												TurtleAction.STOP_LOSS_REASON,
												startOrEnd ? TurtleAction.OUT_ACTION_AT_START
														: TurtleAction.OUT_ACTION_AT_END,
												liquidatePrice2);
							}
						} else {
							act
									.setData(
											TurtleAction.OUT_ACTION,
											TurtleAction.LONG_ACTION,
											TurtleAction.STOP_LOSS_REASON,
											startOrEnd ? TurtleAction.OUT_ACTION_AT_START
													: TurtleAction.OUT_ACTION_AT_END,
											liquidatePrice2);
						}

						this.writer2TradeFile(act.getActionMessage());

						double profit2 = liquidatePrice2 - basePrice2; // 計算獲利

						if (startOrEnd == false && profit2 > -10000) {
							/* 不論現在損益，只要下一單是隔天且同向多單，則續抱 */
							/* 這十年來多一千多點!!! */
							tryContinueTrade = true; /* 可試著保有單 */
							prevTradeType = STOP_LOSS_LONG;
						} else {
							tryContinueTrade = false;
						}

						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, true);						
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_LONG_STAT,
								profit2);
						statSet.enter(StatCalcSet.STOP_LOSS_ALL_OUT, profit2);
						statSet.enter(StatCalcSet.STOP_LOSS_LONG_OUT, profit2);
						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPLOSS_LONG] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addInPrice - addOutPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addInPrice = bar2.close;
								addOutPrice = nextBar2.close;
								// act.setADDData(TurtleAction.ADDTRADE_IN_TOMORROW_OPEN,
								// TurtleAction.ADDTRADE_OUT_TOMORROW_CLOSE,
								// TurtleAction.LONG_ACTION);
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.LONG_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_LONG_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_STOP_LOSS_LONG_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}
					} else if (bar.close <= basePrice - profitStopForShort // 停利
							&& !bull) { // 手上持有 short position = 做空
						inHand = false; // 出場
						prevTrade = "空單,停利出場";
						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[3] == OUT_TRADE_AT_START ? true
								: false;
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交(多單平倉)
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交(多單平倉)

						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.SHORT_ACTION,
								TurtleAction.STOP_PROFIT_REASON,
								startOrEnd ? TurtleAction.OUT_ACTION_AT_START
										: TurtleAction.OUT_ACTION_AT_END,
								liquidatePrice2);
						this.writer2TradeFile(act.getActionMessage());

						double profit2 = basePrice2 - liquidatePrice2; // 計算獲利

						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, false);
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_SHORT_STAT,
								profit2);
						statSet.enter(StatCalcSet.STOP_PROFIT_ALL_OUT, profit2);
						statSet.enter(StatCalcSet.STOP_PROFIT_SHORT_OUT,
								profit2);
						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPPROFIT_SHORT] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.LONG_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addInPrice - addOutPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_SHORT_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_STOP_PROFIT_SHORT_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}
					} else if (bar.close >= basePrice + profitStopForLong // 停利
							&& bull) { // 手上持有 long position = 做多
						inHand = false; // 出場
						prevTrade = "多單,停利出場";
						int nextIndex = it.nextIndex();
						if (nextIndex == barSet.size())
							continue;

						Bar nextBar = barSet.getBar(nextIndex); // 交易
						Bar nextBar2 = barSet2.getBar(nextIndex); // 交易

						boolean startOrEnd = DEFAULT_START_OR_NOT[2] == OUT_TRADE_AT_START ? true
								: false;
						double liquidatePrice = startOrEnd ? nextBar.open
								: nextBar.close; // 假設隔天收盤價成交(多單平倉)
						double liquidatePrice2 = startOrEnd ? nextBar2.open
								: nextBar2.close; // 假設隔天收盤價成交(多單平倉)

						if (bar2.high>bar.high) {
							System.out.println("明天如果期貨開盤>今日期貨收盤,則開盤出場");
						}
						if (nextBar2.open > bar2.close && bar2.high > bar.high) {
							/*開盤出場*/
							startOrEnd = true;
							liquidatePrice2 = nextBar2.open;												  
						} else {							
							  startOrEnd = false;
							  liquidatePrice2 = nextBar2.close;
						}						
						
						TurtleAction act = new TurtleAction(barSet, barSet2,
								nextIndex - 1);
						act.setData(TurtleAction.OUT_ACTION,
								TurtleAction.LONG_ACTION,
								TurtleAction.STOP_PROFIT_REASON,
								startOrEnd ? TurtleAction.OUT_ACTION_AT_START
										: TurtleAction.OUT_ACTION_AT_END,
								liquidatePrice2);
						this.writer2TradeFile(act.getActionMessage());

						double profit2 = liquidatePrice2 - basePrice2; // 計算獲利

						scHoldCalendarDays.enter(diffCalendarDays(nextBar,
								baseBar));
						scHoldTransactionDays.enter(it.nextIndex()
								- baseBarIndex);

						statSet.enter(StatCalcSet.TURTLE_TOTAL_STAT, profit2);
						statSet.enter(StatCalcSet.SIMULATION_PROFIT, liquidatePrice2, average_inprice, trade_count, true);
						if (skipNextTrade ==true) {
							statSet.enter(StatCalcSet.FILTER_SIGNAL_ALL, profit2);
							statSet.enter(StatCalcSet.FILTER_SIGNAL_CONTINUES_PROFIT, profit2);						
						}
						if (!skipNextTrade && statSet.getLeastContinusProfit(StatCalcSet.TURTLE_TOTAL_STAT) > SKIP_NEXT_TRADE_PROFIT) {
							skipNextTrade = true;
							System.out.println("********如不是雙向突破,則下一單不跟********");
						}
						else {
							skipNextTrade = false;
						}
						statSet.enter(StatCalcSet.TURTLE_TOTAL_LONG_STAT,
								profit2);
						statSet.enter(StatCalcSet.STOP_PROFIT_ALL_OUT, profit2);
						statSet
								.enter(StatCalcSet.STOP_PROFIT_LONG_OUT,
										profit2);

						//if (nextBar.close<bar.close && nextBar2.high > bar2.high) {
						//if (nextBar.close < bar.close && nextBar.volume > bar.volume) {						
						//if (nextBar.low < bar.low +30) {
						//	skipNextTrade = true;
						//	System.out.println("下一單如為多單進場,不用進場");
						//}
						//else {
						//	skipNextTrade = false;
						//}				
						if (this.DEFAULT_SUGGEST_ADD_SIGNAL[this.ADD_ACTION_OUT_STOPPROFIT_LONG] == true) {
							double profit = 0;
							TurtleAddAction addAct = new TurtleAddAction(
									barSet, barSet2, nextIndex - 1);
							if (startOrEnd == true) {
								/* 開盤出場,則反向當沖進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								// addInPrice = bar2.close;
								addOutPrice = nextBar2.close;
								// addOutPrice = nextBar2.open;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.SHORT_ACTION, act);
								// act.setADDData(TurtleAction.ADDTRADE_IN_TODAY_CLOSE,
								// TurtleAction.ADDTRADE_OUT_TOMORROW_OPEN,
								// TurtleAction.LONG_ACTION);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (nextBar2.high - addInPrice > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								// profit = addOutPrice-addInPrice;
								profit = addInPrice - addOutPrice;
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
												profit);
							} else {
								/* 收盤出場,則同向加碼進場 */
								double addInPrice = 0;
								double addOutPrice = 0;
								addInPrice = nextBar2.open;
								addOutPrice = nextBar2.close;
								addAct
										.setADDData(
												TurtleAddAction.ADDTRADE_IN_TOMORROW_OPEN,
												TurtleAddAction.ADDTRADE_OUT_TOMORROW_CLOSE,
												TurtleAction.LONG_ACTION, act);
								this.writer2TradeFile(addAct
										.getAdditionActionMessage());

								if (addInPrice - nextBar2.low > HALF_FORCE_STOP_LOSS) {
									profit = -HALF_FORCE_STOP_LOSS;
								} else {
									profit = addOutPrice - addInPrice;
								}
								statSet
										.enter(
												StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
												profit);
							}

							statSet.enter(StatCalcSet.OUT_SIGNAL_ALL_InDay,
									profit);
							statSet.enter(StatCalcSet.OUT_SIGNAL_LONG_InDay,
									profit);
							statSet
									.enter(
											StatCalcSet.OUT_SIGNAL_STOP_PROFIT_LONG_InDay,
											profit);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									profit);
						}
					} else {
						/* 沒賣出的時候, 就投機一下,今天收盤進場,明天開盤就出
						 *  明日收盤賣可能更好,但風險變大,三思
						 *  */
						int nextday = it.nextIndex();
						TurtleAddAction addAct = new TurtleAddAction(barSet,
								barSet2, nextday - 1);
						if (bull && nextday - baseBarIndex == 2) {
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(StatCalcSet.IN_SIGNAL_SECOND_DAY_LONG_InDay,nextBar2.open - bar2.close);							
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
											nextBar2.open - bar2.close);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									nextBar2.open - bar2.close);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.LONG_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						} else if (bull && nextday - baseBarIndex == 4) {
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(	StatCalcSet.IN_SIGNAL_SECOND_DAY_LONG_InDay,nextBar2.open - bar2.close);
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
											nextBar2.open - bar2.close);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									nextBar2.open - bar2.close);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.LONG_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						} else if (bull && nextday - baseBarIndex == 7) {
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(StatCalcSet.IN_SIGNAL_SECOND_DAY_LONG_InDay,nextBar2.open - bar2.close);
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
											nextBar2.open - bar2.close);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									nextBar2.open - bar2.close);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.LONG_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						} else if (!bull && nextday - baseBarIndex == 6) {
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(StatCalcSet.IN_SIGNAL_SECOND_DAY_SHORT_InDay, nextBar2.open - bar2.close);
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_LONG_STAT,
											nextBar2.open - bar2.close);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									nextBar2.open - bar2.close);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.LONG_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						} else if (!bull && nextday - baseBarIndex == 1) { // 1,2,3
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(StatCalcSet.IN_SIGNAL_SECOND_DAY_SHORT_InDay,bar2.close - nextBar2.open);
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
											bar2.close - nextBar2.open);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									bar2.close - nextBar2.open);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.SHORT_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						} else if (!bull && nextday - baseBarIndex == 2) { // 1,2,3							
							Bar nextBar2 = barSet2.getBar(nextday);
							statSet.enter(StatCalcSet.IN_SIGNAL_SECOND_DAY_SHORT_InDay,bar2.close - nextBar2.open);
							statSet
									.enter(
											StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_SHORT_STAT,
											bar2.close - nextBar2.open);
							statSet.enter(
									StatCalcSet.TURTLE_TOTAL_ADDSIGNAL_STAT,
									bar2.close - nextBar2.open);
							addAct.setADDData(
									TurtleAddAction.ADDTRADE_IN_TODAY_CLOSE,
									TurtleAddAction.ADDTRADE_OUT_TOMORROW_OPEN,
									TurtleAction.SHORT_ACTION,
									currentTradeAction);
							this.writer2TradeFile(addAct
									.getAdditionActionMessage());
						}
					}
				}

				if (inHand) {
					dayInHand++;
				} else {
					dayInHand = 0;
				}
			}
		}

		try {
		  BufferedWriter testWriter = new BufferedWriter(new FileWriter("tmp/simulation_history.csv"));
		  StatCalc r = statSet.getStat(StatCalcSet.SIMULATION_PROFIT);
		  ArrayList<Double> his = r.getHistoryList();
		  for (int i=0;i<his.size();i++) {
			  testWriter.write(r.valueList.get(i)+","+his.get(i)+"\n");
			  
		  }
		  testWriter.close();
		} catch (IOException e) {
			System.out.println(e);
		}
		try {
			  BufferedWriter testWriter = new BufferedWriter(new FileWriter("tmp/all_history.csv"));
			  StatCalc r = statSet.getStat(StatCalcSet.TURTLE_TOTAL_STAT);
			  ArrayList<Double> his = r.getHistoryList();
			  for (int i=0;i<his.size();i++) {
				  testWriter.write(r.valueList.get(i)+","+his.get(i)+"\n");
			  }
			  testWriter.close();
			} catch (IOException e) {
				System.out.println(e);
			}
		
			try {
				  BufferedWriter testWriter = new BufferedWriter(new FileWriter("tmp/short_history.csv"));
				  StatCalc r = statSet.getStat(StatCalcSet.TURTLE_TOTAL_SHORT_STAT);
				  ArrayList<Double> his = r.getHistoryList();
				  for (int i=0;i<his.size();i++) {
					  testWriter.write(r.valueList.get(i)+","+his.get(i)+"\n");
				  }
				  testWriter.close();
				} catch (IOException e) {
					System.out.println(e);
				}
				try {
					  BufferedWriter testWriter = new BufferedWriter(new FileWriter("tmp/long_history.csv"));
					  StatCalc r = statSet.getStat(StatCalcSet.TURTLE_TOTAL_LONG_STAT);
					  ArrayList<Double> his = r.getHistoryList();
					  for (int i=0;i<his.size();i++) {
						  testWriter.write(r.valueList.get(i)+","+his.get(i)+"\n");
					  }
					  testWriter.close();
					} catch (IOException e) {
						System.out.println(e);
					}			  
		StringBuffer buf = new StringBuffer();
		String line;

		System.out.println("\n" + statSet);

		Iterator<String> iter = tradeMap.keySet().iterator();
		while (iter.hasNext()) {
			String key = iter.next();
			line = key + "個數:" + tradeMap.get(key) + "\n";
			buf.append(line);
		}		
		logger.info("\n" + buf.toString());
		summary = buf.toString();
		if (IS_NEED_EVALUATOR) {
		  TurtleActEvaluator eval = new TurtleActEvaluator(TurtleAction.allActions, TurtleAddAction.allActions);
			//TurtleActReverseEvaluator eval = new TurtleActReverseEvaluator(TurtleAction.allActions);
		  eval.exec();		
		}
		System.out.println(testCalc);
		System.out.print("總單");statSet.knownContinueFailProb(StatCalcSet.TURTLE_TOTAL_STAT, 3);
		System.out.print("空單");statSet.knownContinueFailProb(StatCalcSet.TURTLE_TOTAL_SHORT_STAT, 6);
		System.out.print("多單");statSet.knownContinueSuccessProb(StatCalcSet.TURTLE_TOTAL_LONG_STAT, 5);
		System.out.println(statSet.testCalc);
		return statSet.getStat(StatCalcSet.TURTLE_TOTAL_STAT).getSum();
	}

	private void writer2TradeFile(String content) {
		try {
			writer.write(content + "\n");
		} catch (IOException e) {
			System.out.println(e);
		}
	}

	private static Logger loadDefaultLogger() {
		Properties logp = new Properties();
		try {
			logp.load(PriceData.class.getClassLoader().getResourceAsStream(
					"turtle/system/pt/j4util.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		PropertyConfigurator.configure(logp);

		return Logger.getRootLogger();
	}

	public static void main(String[] args) throws IOException {
		/**
		 * 使用新的資料
		 * 
		 */
		LOSS_STOP_RANGE_FOR_LONG_CONSERVATIVE = new int[] { 30, 30 }; // 做多停損點數實驗區間
		PROFIT_STOP_RANGE_FOR_LONG_CONSERVATIVE = new int[] { 195, 195 }; // 做多停利點數實驗區間
		LOSS_STOP_RANGE_FOR_SHORT_CONSERVATIVE = new int[] { 55, 55 }; // 做空停損點數實驗區間
		PROFIT_STOP_RANGE_FOR_SHORT_CONSERVATIVE = new int[] { 170, 170 }; // 做空停利點數實驗區間
		inAndOut_CONSERVATIVE = new int[][] { // 特別觀察組合
		{ 2, 9, 2, 5 } };
		
		PriceDataRefineSellSystem cons = new PriceDataRefineSellSystem(
				PriceDataRefineSellSystem.STRATEGY_CONSERVATIVE,
				DailyStopProfitExec.WTX0_PREFIX_FN
						+ DailyStopProfitExec.FN_SUFFIX,
				DailyStopProfitExec.WTX1_PREFIX_FN
						+ DailyStopProfitExec.FN_SUFFIX);

	}
}
